package tcpserver.client;

import java.io.*;
import java.net.*;

import utils.sl651.SL651CommonUtil;
import utils.sl651.SL651GenMsgUtil;

/**
 * Netty TCP服务器测试客户端
 * 
 * 连接到端口8281的Netty服务器，发送SL651协议测试报文
 */
public class NettyServerTestClient {
    
    private static final String HOST = "localhost";
    private static final int PORT = 8281;
    
    private Socket socket;
    private PrintWriter writer;
    private BufferedReader reader;
    
    /**
     * 连接到Netty服务器
     */
    public boolean connect() {
        try {
            socket = new Socket(HOST, PORT);
            writer = new PrintWriter(new OutputStreamWriter(socket.getOutputStream(), "UTF-8"), true);
            reader = new BufferedReader(new InputStreamReader(socket.getInputStream(), "UTF-8"));
            
            System.out.println("=================================");
            System.out.println("   🚀 成功连接到Netty服务器！");
            System.out.println("   服务器地址: " + HOST + ":" + PORT);
            System.out.println("=================================");
            
            // 启动接收消息的线程
            startReceiveThread();
            
            return true;
            
        } catch (IOException e) {
            System.err.println("连接Netty服务器失败: " + e.getMessage());
            return false;
        }
    }
    
    /**
     * 启动接收消息的线程
     */
    private void startReceiveThread() {
        Thread receiveThread = new Thread(() -> {
            try {
                String response;
                while ((response = reader.readLine()) != null) {
                    System.out.println("📨 [" + getCurrentTime() + "] 服务器响应: " + response);
                }
            } catch (IOException e) {
                if (!socket.isClosed()) {
                    System.err.println("接收消息失败: " + e.getMessage());
                }
            }
        });
        
        receiveThread.setDaemon(true);
        receiveThread.start();
    }
    
    /**
     * 发送消息
     */
    public void sendMessage(String message) {
        if (writer != null) {
            writer.println(message);
            System.out.println("📤 [" + getCurrentTime() + "] 发送: " + message);
        } else {
            System.err.println("连接未建立");
        }
    }
    
    /**
     * 获取当前时间
     */
    private String getCurrentTime() {
        return SL651CommonUtil.getCurrentTime();
    }
    
    /**
     * 断开连接
     */
    public void disconnect() {
        try {
            if (writer != null) {
                writer.close();
            }
            if (reader != null) {
                reader.close();
            }
            if (socket != null) {
                socket.close();
            }
            System.out.println("🔌 连接已断开");
        } catch (IOException e) {
            System.err.println("断开连接失败: " + e.getMessage());
        }
    }
    
    /**
     * 简化的CRC16校验计算（IBM CRC-16）
     */
    private String calculateCrc16(String hexString) {
        return SL651CommonUtil.calculateCrc16(hexString);
    }
    
    /**
     * 十六进制字符串转换为字节数组
     */
    private byte[] hexStringToByteArray(String hexString) {
        return SL651CommonUtil.hexStringToByteArray(hexString);
    }
    
    /**
     * ASCII字符串转换为十六进制
     */
    private String asciiToHex(String ascii) {
        return SL651CommonUtil.asciiToHex(ascii);
    }



    /**
     * 处理用户提供的SL651报文（ASCII编码格式）
     * 将其转换为可发送的HEX字节格式
     */
    private String processUserSL651Message() {
        return "SL651GenMsgUtil.processUserAsciiSL651Message()";
    }
    
    /**
     * 生成标准HEX编码格式的SL651报文（以7E7E开头）
     */
    private String generateHexFormatSL651Message() {
        return SL651GenMsgUtil.generateHexFormatSL651Message();
    }
    
    /**
     * 发送用户提供的SL651报文和标准HEX格式对比
     */
    public void sendUserSL651Messages() {
        System.out.println("\n🎯 开始发送用户SL651报文和标准对比...\n");
        
        try {
            // 1. 发送用户提供的ASCII编码格式报文
            System.out.println("1️⃣ 发送用户提供的ASCII编码SL651报文");
            String userMessage = processUserSL651Message();
            System.out.println("   ASCII格式报文长度: " + userMessage.length() + " 字符");
            sendMessage(userMessage);
            Thread.sleep(2000);
            
            // 2. 发送标准HEX编码格式报文对比
            System.out.println("2️⃣ 发送标准HEX编码格式报文（7E7E开头）");
            String hexMessage = generateHexFormatSL651Message();
            System.out.println("   HEX格式报文长度: " + hexMessage.length() + " 字符");
            sendMessage(hexMessage);
            Thread.sleep(2000);
            
            // 3. 分段发送用户报文（测试服务器处理能力）
            System.out.println("3️⃣ 分段发送用户报文测试");
            
            // 头部（报文头）
            String headerPart = userMessage.substring(0, Math.min(48, userMessage.length()));
            System.out.println("   头部: " + headerPart);
            sendMessage(headerPart);
            Thread.sleep(1000);
            
            // 数据部分
            if (userMessage.length() > 48) {
                int startPos = 48;
                int endPos = Math.min(startPos + 100, userMessage.length() - 8);
                String dataPart = userMessage.substring(startPos, endPos);
                System.out.println("   数据部分: " + dataPart);
                sendMessage(dataPart);
                Thread.sleep(1000);
            }
            
            // 尾部（CRC校验）
            String tailPart = userMessage.substring(userMessage.length() - 8);
            System.out.println("   尾部CRC: " + tailPart);
            sendMessage(tailPart);
            Thread.sleep(1000);
            
            System.out.println("\n✅ 用户SL651报文发送完成！");
            System.out.println("📊 对比结果:");
            System.out.println("   ASCII编码(01开头): 适用于ASCII字符传输信道");
            System.out.println("   HEX编码(7E7E开头): 适用于二进制数据传输信道\n");
            
        } catch (InterruptedException e) {
            System.err.println("发送过程被中断: " + e.getMessage());
        }
    }
    
    /**
     * 发送SL651协议测试报文（完整标准报文）
     */
    public void sendSL651TestMessages() {
        System.out.println("\n🧪 开始发送SL651-2014标准协议报文到Netty服务器...\n");
        
        try {
            // 测试1：标准SL651链路维持报文（功能码2F）
            System.out.println("1️⃣ 发送SL651链路维持报文（功能码2F）");
            String linkMessage = SL651GenMsgUtil.generateAsciiLinkMaintenanceMessage();
            System.out.println("   报文长度: " + linkMessage.length() + " 字符");
            sendMessage(linkMessage);
            Thread.sleep(1000);
            
            // 测试2：SL651测试报文（功能码30）
            System.out.println("2️⃣ 发送SL651测试报文（功能码30）");
            String testMessage = SL651GenMsgUtil.generateHexTestMessage();
            System.out.println("   报文长度: " + testMessage.length() + " 字符");
            sendMessage(testMessage);
            Thread.sleep(1000);
            
            // 测试3：SL651定时报文（功能码32）
            System.out.println("3️⃣ 发送SL651定时报文（功能码32）");
            String timerMessage = SL651GenMsgUtil.generateAsciiTimerMessage();
            System.out.println("   报文长度: " + timerMessage.length() + " 字符");
            sendMessage(timerMessage);
            Thread.sleep(1000);
            
            // 测试4：SL651加报报文（功能码33）
            System.out.println("4️⃣ 发送SL651加报报文（功能码33）");
            String addMessage = SL651GenMsgUtil.generateHexAddMessage();
            System.out.println("   报文长度: " + addMessage.length() + " 字符");
            sendMessage(addMessage);
            Thread.sleep(1000);
            
            // 测试5：SL651小时报文（功能码34）
            System.out.println("5️⃣ 发送SL651小时报文（功能码34）");
            String hourMessage = SL651GenMsgUtil.generateHexHourMessage();
            System.out.println("   报文长度: " + hourMessage.length() + " 字符");
            sendMessage(hourMessage);
            Thread.sleep(1000);
            
            // 测试6：SL651人工置数报文（功能码35）
            System.out.println("6️⃣ 发送SL651人工置数报文（功能码35）");
            String manualMessage = SL651GenMsgUtil.generateAsciiManualDataMessage();
            System.out.println("   报文长度: " + manualMessage.length() + " 字符");
            sendMessage(manualMessage);
            Thread.sleep(1000);
            
            // 测试7：ASCII格式报文（兼容测试）
            System.out.println("7️⃣ 发送SL651 ASCII格式报文兼容测试");
            sendMessage("$WL125.67M" + getCurrentTime().replace(":", "") + "#");
            Thread.sleep(1000);
            
            System.out.println("\n✅ SL651-2014标准报文测试完成！\n");
            System.out.println("📊 所有报文均符合SL651-2014标准要求：");
            System.out.println("   • 包含完整的报文头部（SOH+中心站+遥测站+密码+功能码）");
            System.out.println("   • 正确的数据格式（STX+流水号+时间+数据+ETX）");
            System.out.println("   • CRC16校验码保证数据完整性");
            System.out.println("   • 最小报文长度大于90字符（符合SL651要求）\n");
            
        } catch (InterruptedException e) {
            System.err.println("发送过程被中断: " + e.getMessage());
        }
    }
    
    /**
     * 主程序入口
     */
    public static void main(String[] args) {
        NettyServerTestClient client = new NettyServerTestClient();
        
        // 连接Netty服务器
        if (!client.connect()) {
            System.err.println("无法连接到Netty服务器，请确保服务器正在运行在端口" + PORT);
            return;
        }
        
        try {
            // 等待连接稳定
            Thread.sleep(1000);
            
            // 首先发送用户提供的SL651报文
            client.sendUserSL651Messages();
            
            // 等待响应
            Thread.sleep(2000);
            
            // 然后发送标准测试报文
            client.sendSL651TestMessages();
            
            // 等待响应
            Thread.sleep(3000);
            
            // 发送退出命令
            System.out.println("6️⃣ 发送退出命令");
            client.sendMessage("QUIT");
            Thread.sleep(1000);
            
        } catch (InterruptedException e) {
            System.err.println("程序被中断: " + e.getMessage());
        } finally {
            client.disconnect();
            System.out.println("\n🎯 Netty服务器测试完成！");
            System.out.println("📊 测试了SL651协议在Netty高性能服务器上的处理效果");
        }
    }
}